<?php
/**
 * Abstract.php
 *
 * @author		b.wenneker <b.wenneker@gmail.com>, 2010
 */
abstract class Application_Model_Search_Index_Abstract{
	
	/**
	 * Lucene index.
	 *
	 * @var Zend_Search_Lucene_Interface $_index
	 */
	protected $_index = null;
	
	/**
	 * Name of the identifier field in the index documents.
	 *
	 * @var string $_identifierFieldName
	 */
	protected $_identifierFieldName = 'index/identifier';
	
	/**
	 * updateDocument() - Update the index with the index data. Updating is done by removing any
	 * duplicates and then reinsert a new document.
	 *
	 * @author b.wenneker <b.wenneker@gmail.com>, 2010
	 * @param array|mixed $indexData Data to build the document to update from.
	 */
	abstract public function updateDocument($indexData);
	
	/**
	 * Returns the directory where the index is stored.
	 *
	 * @author b.wenneker <b.wenneker@gmail.com>, 2010
	 * @return string Directory where the index is stored.
	 */
	public static function getIndexDirectory(){
		$path = sys_get_temp_dir();
		return $path;//APPLICATION_PATH .'/models/Search/Index/data';
	}
	
	/**
	 * Initializes the index if not done yet.
	 *
	 * @author b.wenneker <b.wenneker@gmail.com>, 2010
	 */
	public function getIndex()
	{
		
		if(is_null($this->_index)){
			$this->_initIndex();
		}
		
		return $this->_index;
	}
	
	/**
	 * Returns a new document instance. This method is created so that new
	 * document types can be added in the future.
	 *
	 * @author b.wenneker <b.wenneker@gmail.com>, 2010
	 * @param array|mixed $indexData
	 * @return Zend_Search_Lucene_Document Index document.
	 */
	public function getNewDocumentInstance($indexData = null){
		
		$document = new Zend_Search_Lucene_Document();
		
		if(! is_null($indexData)){
			$this->addIdentifierField($document, $this->getIdentifierFieldValue($indexData));
		}
		return $document;
	}
	
	/**
	 * Returns the identifier field name.
	 *
	 * @author b.wenneker <b.wenneker@gmail.com>, 2010
	 * @return string The identifier field name.
	 */
	public function getIdentifierFieldName()
	{
		
		return $this->_identifierFieldName;
	}
	
	/**
	 * Returns a value that is used to identify the document containing the
	 * indexdata.
	 *
	 * @author b.wenneker <b.wenneker@gmail.com>, 2010
	 * @param array|mixed $indexData
	 */
	abstract public function getIdentifierFieldValue($indexData);
	
	/**
	 * Adds the identifier value to the document at the right index name.
	 *
	 * @author b.wenneker <b.wenneker@gmail.com>, 2010
	 * @param Zend_Search_Lucene_Document $document
	 * @param string $identifierValue
	 */
	public function addIdentifierField(Zend_Search_Lucene_Document &$document, $identifierValue)
	{
		
		$document->addField(Zend_Search_Lucene_Field::Keyword($this->getIdentifierFieldName(), $identifierValue));
	}
	
	/**
	 * Initializes the index.
	 *
	 * @author b.wenneker <b.wenneker@gmail.com>, 2010
	 */
	protected function _initIndex(){
		
		$indexDirectory		= $this->getIndexDirectory();
		
		try{
			$this->_index 	= Zend_Search_Lucene::open($indexDirectory);
		}catch(Zend_Search_Lucene_Exception $e){
			// Index probably does not yet exist, create a new one.
			$this->_index 	= Zend_Search_Lucene::create($indexDirectory);
		}
	}
	
	public function clear(){
		$indexDirectory		= $this->getIndexDirectory();
		$this->_index 		= Zend_Search_Lucene::create($indexDirectory);
	}
	
	/**
	 * Removes duplicate entries given the identifier that is generated from the
	 * given data array.
	 *
	 * @author b.wenneker <b.wenneker@gmail.com>, 2010
	 * @param array|mixed $indexData
	 */
	protected function _deleteDuplicates($indexData){
		
		$index				= $this->getIndex();
		$identifierValue 	= $this->getIdentifierFieldValue($indexData);
		$duplicates			= $index->find(sprintf('%s:"%s"',$this->getIdentifierFieldName(), $identifierValue));
		
		foreach($duplicates as $duplicate){
			$index->delete($duplicate->id);
		}
		
		$index->commit();
	}
}